/* -*- Mode: C++; c-basic-offset: 4; -*- */
// Copyright (C) 2003, 2004 by BiRC -- Bioinformatics Research Center
//                             University of Aarhus, Denmark
//                             Contact: Thomas Mailund <mailund@birc.dk>

#include <cassert>

using namespace std;

#include "unrootedtree.hh"
#include "unrootedtree-builder.hh"

#include "rootedtree.hh"
#include "dag.hh"
#include "S.hh"

SMap smap;

void
build_tree1(UnrootedTreeBuilder &builder)
{

    /*  foo      baz          qux
     *    \       |          /
     *     `------+---------'
     *    /                  \
     *  bar                   qax
     */
    
    builder.push_internal();
    {
	builder.add_leaf("baz");

	builder.push_internal();
	{
	    builder.add_leaf("foo");
	    builder.add_leaf("bar");
	}
	builder.pop_internal();

	builder.push_internal();
	{
	    builder.add_leaf("qux");
	    builder.add_leaf("qax");
	}
	builder.pop_internal();
    }
    builder.pop_internal();
}

void
build_tree2(UnrootedTreeBuilder &builder)
{

    /*  baz      foo          qux
     *    \       |          /
     *     `------+---------'
     *    /                  \
     *  bar                   qax
     */
    
    builder.push_internal();
    {
	builder.add_leaf("foo");

	builder.push_internal();
	{
	    builder.add_leaf("baz");
	    builder.add_leaf("bar");
	}
	builder.pop_internal();

	builder.push_internal();
	{
	    builder.add_leaf("qux");
	    builder.add_leaf("qax");
	}
	builder.pop_internal();
    }
    builder.pop_internal();
}



typedef void (*tree_func_t)(UnrootedTreeBuilder &);
struct Test {
    tree_func_t tree1;
    tree_func_t tree2;
    int         count;
};

Test tests[] = {
    {build_tree1, build_tree1, 10},
    {build_tree1, build_tree2,  6},
    {build_tree2, build_tree1,  6},
    { 0 },
};

void
test(Test &test)
{
    DAG dag(smap);

    UnrootedTreeBuilder hbuilder(smap);
    test.tree2(hbuilder);
    RootedTree ht(hbuilder.build_tree(), "foo");
    dag.merge(ht, "cat", 101);

    UnrootedTreeBuilder bbuilder(smap);
    test.tree1(bbuilder);
    RootedTree bt(bbuilder.build_tree(), "foo");
    dag.merge(bt, "fish", 49);

    dag.count();
    assert(large_int_t(static_cast<unsigned long>(test.count)) == dag[0][0]);
}

static large_int_t test_results[][3] = {
    { 10UL, 10UL,  6UL },
    {  6UL,  6UL, 10UL },
    { 10UL, 10UL,  6UL },
};

int
main()
{
    SMap smap;

    for (int i = 0; tests[i].tree1 == 0; ++i) {
	test(tests[i]);
	smap.ResetAll();
    }

    DAG dag(smap);
    for (int i = 0; tests[i].tree1 == 0; ++i) {

	UnrootedTreeBuilder bbuilder(smap);
	tests[i].tree1(bbuilder);
	RootedTree bt(bbuilder.build_tree(), "foo");
	dag.merge(bt, "bonzo", 99);

    }

    dag.count ();

    for (int i = 0; tests[i].tree1 == 0; ++i) {

	for (unsigned int j = 0; j < dag[i].size(); ++j)
	    assert(dag[i][j] == test_results[i][j]);

    }

    return 0;
}
